# Shuttle 0.1 transfer module
# (c) 2008-2009 NIXON Development Corporation.

import local, format, wx
from time import clock

class main():
	intMode = -1
	intMeasure = 0
	intSecs = 0
	blTimer = False
	intLayout = 0
			
	def showProgress(self):
		strTransfer = format.parseSize(self.intMeasure)
		
		strEnd = strTransfer + '/' + self.strTotal
		self.handle.stTransProgress.SetLabel(strEnd)
		intSecs = self.handle.mFTP.tl.intSecs
		
		if self.intMeasure != 0 and intSecs != 0:
			speed = self.intMeasure / intSecs
		else:
			speed = 0
		
		strTime = format.parseTime(format.remain(intSecs, self.intMeasure, self.intSize))
		strRemain = format.parseSize(speed) + '/s'
		if strTime:
			strRemain += ' - ' + strTime + ' remaining'
		self.handle.stTransRemain.SetLabel(strRemain)
		
		self.handle.pnQueue.Layout()
					
	def __init__(self, frame, hftp):
		self.handle = frame
		self.hftp = hftp
		
	def transferFile(self, dlul, strFrom, strTo, box=None, callback=None):
		self.transferBusy = True
		self.handle.blStop = False
		self.handle.mFTP.tl.block = True
		self.handle.doQueue(-1)
		self.intMode = dlul
		
		strFile = format.getNameFromPath(strFrom)
		blAscii = self.needsAscii(strFrom)
		self.blAscii = blAscii
		self.handle.stTransName.SetLabel(strFile)
		
		auto = self.handle.blAuto
		self.intMeasure = 0

		if dlul == 0 or dlul == -2: #download/image preview
			strIcon = 'download'
			self.intSize = self.handle.dirList.getSizes(strFrom)
			if dlul == 0:
				strOpen = strTo + '/' + strFile
			else:
				strOpen = strTo
		else:
			strIcon = 'upload'
			self.intSize = local.getInfo(strFrom)[2]
			
		self.handle.sbActivity.SetBitmap(wx.Bitmap('icons/global/' + strIcon + '.png'))
		self.handle.stTransFrom.SetLabel(strFrom)
		self.handle.stTransTo.SetLabel(strTo)
		self.handle.pnQueue.Layout()
		self.strTotal = format.parseSize(self.intSize)

		if dlul == 0 or dlul == -2:
			func = self.getFile
			tpArgs = (blAscii, strFrom)
			
			if blAscii: strArg = 'w'
			else: strArg = 'wb'
			self.fl = open(strOpen, strArg)	
		else:
			func = self.putFile
			tpArgs = (blAscii, strTo + '/' + strFile)
			
			if blAscii: strArg = 'r'
			else: strArg = 'rb'
			self.fl = open(strFrom, strArg)

		self.strFrom = strFrom
		self.strTo = strTo
		
		try:
			func(*tpArgs)
			
		except error_perm, e:
			self.frame.pnRemote.doStatus(True, True)
			self.frame.pnRemote.statusText.SetLabel('Permission denied.')
			
		except Exception, e:
			print('A transfer has failed.')
		finally:
			self.fl.close()
			self.intMeasure = 0
			self.intMode = -1
			self.intSecs = 0
			self.transferBusy = False
		
		if self.handle.blClosing:
			self.handle.Destroy()
		
		if not self.handle.blStop:
			if box and box.Label == strTo:
				if box.FindItem(-1, strFile) == -1:
					box.InsertImageStringItem(box.GetItemCount() + 1, strFile, 0)
					
			if dlul == 1:
				try:
					lstNames = self.handle.dirList.dnames[strTo]
					try:
						lstNames.index(strFile)
					except:
						lstNames.append(strFile)
						self.handle.dirList.dnames[strTo] = lstNames
						
						tpInfo = ['-rwx------', 0]
						for x in local.getInfo(strFrom):
							tpInfo.append(x)
						tpInfo.append(strFile)
							
						self.handle.dirList.dfiles[strTo + '/' + strFile] = tpInfo
				except: pass
				
			if callback:
				callback()

	def measureFile(self, input):
		self.intMeasure += len(input)
		self.handle.gaugeProgress.SetValue(float(self.intMeasure) / float(self.intSize) * 100)
		
		if self.intMode == 0 or self.intMode == -2:
			if self.blAscii:
				self.writeLine(input)
			else:
				self.fl.write(input)
				
		if self.handle.mFTP.tl.timer.needsUpdate:
			self.handle.mFTP.tl.timer.needsUpdate = False
			self.showProgress()
		
	def writeLine(self, line):
		self.fl.write(line + '\n')
			
	def needsAscii(self, fname):
		if self.handle.blAuto:
			pos = fname.rfind('.')
			ext = fname[pos:]
			ascii = self.handle.asclist.find(ext) != -1
		else:
			ascii = self.handle.getTransferType() == 1

		return ascii
		
	def getFile(self, blAscii, pwf): # modified for abort capability
		if blAscii: strType = 'A'
		else: strType = 'I'
		
		ftp = self.handle.mFTP.hftp
		ftp.voidcmd('TYPE ' + strType)
		conn = ftp.transfercmd('RETR ' + pwf, rest=None)
		bytes_recv = 0
		while 1:
			chunk = conn.recv(8192)
			# stop transfer while it isn't finished yet
			self.measureFile(chunk)
			if not(chunk) or self.handle.blStop:
				break
			bytes_recv += len(chunk)
			
		conn.close()
		ftp.voidresp()
		
	def putFile(self, blAscii, pwf):
		if blAscii: strType = 'A'
		else: strType = 'I'
		CRLF = '\r\n'
		
		ftp = self.handle.mFTP.hftp
		ftp.voidcmd('TYPE ' + strType)
		conn = ftp.transfercmd('STOR ' + pwf)
		while 1:
			if strType == 'A':
				buf = self.fl.readline()
			else:
				buf = self.fl.read(8192)
			self.measureFile(buf)
			if not(buf) or self.handle.blStop: break
			if strType == 'A':
				if buf[-2:] != CRLF:
					if buf[-1] in CRLF: buf = buf[:-1]
					buf = buf + CRLF
			conn.sendall(buf)
			
		conn.close()
		ftp.voidresp()